昨天把 CDN 接上了 PokeThreads,圖片跟影片不再經過 Application Server,直接由 CDN 搭配 Object Storage 提供服務:

但這裡其實跳過了一個環節:
Pikachu 上傳一張 20MB 的原始照片,到這張照片變成 CDN 上那張輕巧的圖片之間,中間到底發生了什麼事?
總不可能不處理 20MB 的原始檔案,直接拿去讓全世界的人下載吧。
先釐清一件事:使用者上傳的檔案,跟系統實際拿來服務的檔案,通常不是同一份。
原始檔案可能:
如果什麼都不做,直接把原始檔案丟給 CDN 快取,代價是每個人下載的流量都變大、PokeThreads 的頻寬帳單也會跟著變大。
所以在「上傳」跟「CDN 提供服務」之間,需要一段 Processing(處理) 的過程。
延續昨天的原則——媒體檔案不應該經過 Application Server,這個原則在「上傳」這一端一樣適用。
如果讓 Client 把檔案傳給 Application Server,再由 Server 轉傳到 Object Storage,等於讓 Server 白白扛了一次檔案傳輸的 Network Load。
更好的做法是 Pre-signed URL(預先簽署網址):

Application Server 全程只做兩件事:驗證身份、簽發網址,真正的檔案位元組完全不會經過它。
這跟昨天「CDN 讓下載不經過 Server」是一樣概念,只是換成上傳方向。
檔案進到 Object Storage 之後,會觸發一個 Processing Worker,執行:
這些工作有一個共同點:都不需要讓使用者在原地等待。
這其實跟「事件發生後,丟給背景服務慢慢處理」是同一種模式,會在後面的系列文章討論 Notification 時,把這種「非同步 + Worker」的做法正式定義清楚;這裡先知道 Processing 是用類似的方式在背景執行就好。
Worker 處理完畢後,把結果寫回另一個位置(或加上版本化的檔名),之後 CDN 快取的就是這份處理過、體積小很多的檔案,而不是使用者上傳的原始檔。
這裡有個很實際的問題:
Processing 需要時間,這段期間 Pikachu 的貼文該顯示什麼?
最簡單的做法,是幫 Post 加一個處理狀態欄位:
PENDING / PROCESSING / READY / FAILED)
狀態的轉換大致是:
PENDING(剛上傳,等待處理)
↓
PROCESSING(Worker 正在處理) --失敗--> FAILED
| 處理成功
↓
READY(處理完成,可以顯示 processed_url)
在 media_status 還不是 READY 之前,Feed 上可以先顯示一個 Placeholder(例如模糊縮圖或載入中的動畫),等狀態變成 READY,前端才把畫面換成真正的 processed_url。
這樣 Pikachu 發文之後不需要卡住等處理完成,貼文的文字內容可以馬上出現,圖片則是晚一點點才補上。
除了「先上傳原始檔、再非同步處理」,另一種常見做法是 Client-side Processing:在使用者裝置上先做一輪基本壓縮、裁切,再上傳。
| Server-side Processing | Client-side Processing | |
|---|---|---|
| 上傳流量 | 較大(傳原始檔) | 較小(先在裝置端壓縮過) |
| 處理能力 | 可以用較強的運算資源,效果較一致 | 受限於使用者裝置效能,結果可能不一致 |
| 實作複雜度 | 需要 Worker、狀態機 | 需要在每個前端平台各自實作 |
| 常見場景 | 需要多種輸出格式、影片轉碼 | 想先擋掉明顯過大的檔案,減少上傳等待時間 |
實務上這兩者通常會搭配使用:Client 端先做基本的裁切跟壓縮,減少上傳時間;真正決定最終畫質、格式、多解析度輸出的工作,還是交給 Server 端的 Processing Worker 統一處理。
把今天的流程和昨天的 CDN 架構接在一起看:

Application Server 在這整條路徑上,只出現在最開頭簽發網址、以及讀寫 media_status 這個欄位,真正的檔案傳輸與運算,全部交給 Object Storage、Worker 跟 CDN 分工完成。
今天把「使用者上傳一個檔案」到「CDN 上出現一份優化過的檔案」之間的空白補上了:
Upload(Pre-signed URL,繞過 App Server)
↓
Processing(非同步:resize / compress / transcode)
↓
CDN(服務處理後的檔案)
到目前為止,PokeThreads 已經能好好處理「使用者主動看到」的內容:文字、圖片、影片。
但社群平台還有一種訊息,是系統要「主動推給使用者」的,例如「有人按讚了你的貼文」。這是接下來要處理的功能。